﻿namespace Lesson_8_ref和out的区别
{
    internal class Program
    {
        #region 知识点一 学习ref和out的原因
        //它们可以解决函数间的传参问题，可以让函数间传递参数的形式更加灵活，可以提高代码的可读性和可维护性。

        static void ChangeValue(int value)
        {
            value = 3;
        } 

        static void ChangeArrayValue(int[] arr)
        {
            arr[0] = 99;
        }

        static void ChangeArray(int[] arr)
        {
            //重新申明了一个 数组
            arr = new int[] { 10, 20, 33 };
        }
        #endregion
         
        #region 知识点二 ref和out的使用
        //函数参数的修饰符
        //当传入的值类型参数在内部修改时，或者引用类型参数在内部重新申明时
        //外部的值会发生变化

        //ref 修饰符
        static void ChangeValueRef(ref int value)
        {
            value = 3;
        }

        static void ChangeArrayRef(ref int[] arr)
        {
            arr = new int[] { 10, 20, 33 };
        }

        //out 修饰符
        static void ChangeValueOut(out int value)
        {
            value = 3;
        }

        static void ChangeArrayOut(out int[] arr)
        {
            arr = new int[] { 10, 20, 33 };
        }
        #endregion

        #region 知识点三 ref和out的区别
        //ref 和 out 都是用来传递参数的修饰符，但是它们的区别在于：
        //ref 传递的是地址，out 传递的是值。
        //ref 传递的是地址，所以在函数内部修改参数的值，会影响到外部的值。
        //out 传递的是值，所以在函数内部修改参数的值，不会影响到外部的值。

        //1.ref传入的变量必须初始化 out不用
        //2.out转入的变量必须在内部赋值 ref不用

        //ref传入的变量必须初始化 但是在内部 可改可不改
        //out传入的变量不用初始化 但是在内部 必须修改该值（必须赋值）

        #endregion

        //总结
        //1.ref和out的作用：可以解决函数间的传参问题，可以让函数间传递参数的形式更加灵活，可以提高代码的可读性和可维护性。
        //2.ref和out的区别：ref传递的是地址，out传递的是值。ref在函数内部修改参数的值，会影响到外部的值。out在函数内部修改参数的值，不会影响到外部的值。
        //3.ref传入的变量必须初始化，out传入的变量不用初始化，但是在内部必须修改该值。

        #region 练习题
        static bool CheckLogin(string name, string passWord, ref string info)
        {
            if( name == "admin")
            {
                if( passWord == "8888")
                {
                    info = "登录成功";
                }
                else
                {
                    info = "密码错误";
                    return false;
                }
            }
            else
            {
                info = "用户名错误";
                return false;
            }
            return true;
        }
        #endregion
        static void Main(string[] args)
        {
            Console.WriteLine("ref和out");

            int a = 1;
            ChangeValue(a);
            Console.WriteLine(a);

            ChangeValueRef(ref a);
            Console.WriteLine(a);

            ChangeValueOut(out a);
            Console.WriteLine(a);

            int[] arr2 = { 1, 2, 3 };
            ChangeArrayValue(arr2);
            Console.WriteLine(arr2[0]);//99

            ChangeArray(arr2);
            Console.WriteLine(arr2[0]);//99

            ChangeArrayRef(ref arr2);
            Console.WriteLine(arr2[0]);//10

            ChangeArrayOut(out arr2);
            Console.WriteLine(arr2[0]);//10

            #region 练习题
            Console.WriteLine("请输入用户名");
            string name = Console.ReadLine();
            Console.WriteLine("请输入密码");
            string passWord = Console.ReadLine();
            string info = "";

            while( !CheckLogin(name, passWord, ref info))
            {
                Console.WriteLine(info);
                Console.WriteLine("请输入用户名");
                name = Console.ReadLine();
                Console.WriteLine("请输入密码");
                passWord = Console.ReadLine();
            }
            Console.WriteLine(info);
            #endregion
        }
    }
}
